циклы+массивы
читай статьи
и все более менее нормальные карты сделаны людьми которые прочли все статьи
та же дота например(хотя она не особо нормальная)
Бтв, про сбор команды - для продвинутых сущностей нередко исправлять за другими оказывается тяжелее, чем делать самому, важно создать максимально комфортные условия для созидания, вот для чего деньги не лишние, а уж дело и самому можно делать.
И, да, тема-то не про то, надо это или не надо, а про то, как лучше это сделать, я про это и в стартовом сообщении написал.
Я на крайний сам вопрос по варианту 3 проверю и/или будет сделан выбор между третьим вариантом, вторым, каким-то ещё и отказом от Cooldown Reduction, но если кто поможет - спасибо.
Ну качаешь остюда JNGP, тут поправлено туча багов, спс Ханашиби.
Ставим по инструкции, запускаем ро, потом отрубаем USWE опции вроде там кастом тайслетов да кастом гуи триггеров, оно нафиг ненадо и нередко ломает совместимость с другими редакторами карт wc3.
Сжасс там есть, все должно изи работать.
Если нужен мемхак, скину код из своей карты с инструкциями что к чему.
Еще вопросы?
самая лучшая, на мой взгляд, связка - это отлов урона + список событий, привязанный к каждому юниту. Так сделано в YouTD, к примеру. Там даже карта есть DevKit (для создания своих башен) с открытым кодом всех систем. Там можно посмотреть, как это сделано. А так - лучше не бежать от jass, как чёрт от ладана, а сразу разобраться в нём. я в своё время разобрался в нём за пару дней, хотя к программированию вообще не имею никакого отношения. А можно делать всё в wurst сразу, а не в vjass. Короче - привычка делать всё на гуи принесёт потом проблемы, если из карты что-то приличное сделать хочется, потому что всё равно придётся всё переделывать. Да и чё такого страшного в джассе? Душу вроде никому продавать не надо за его изучение.
Вам наверное будет проще взять доспехи горного великана, а защиту не трогать.
Помнится где то была похожая тема, там формула в константах, т.е в таблице, основной дополнительный и рассчет защиты. Но как помне проще 0 защиты, тип без защиты, а доспехами великана регулируйте как душе угодно.
Т.е. ты сначала отдаешь от героя в рюкзак, а потом сразу же забираешь из рюкзака герою? И нафига? Нет, я понял, что у тебя с логикой туго, но все равно должен спросить.
Для простоты и аналогичности: создаёшь третьего юнита, кидаешь ему шмот из рюкзака, кидаешь шмот героя в рюкзак, кидаешь из третьего юнита в героя.
Новые функции в ГУИ, к примеру перемещение точек и их удаление, так же проверка скриптов, если будет ошибка в скрипте, он выдаст ошибку. Можно изменить ID объекта, удобная вещь, не запутаешься, когда переносишь скрипты со строками фиксации (к примеру точка (массив)), если нет её в проекте, она появится автоматически (удобно для переноса скрипта с болванки на проект). Оптимизация. И это ещё не все функции.
На мой взгляд удобно, но есть один минус, когда копируешь текст, он выдаёт не понятные иероглифы, приходится пару раз изменить текст, потом брать его в буфер обмена.
Сильный ии при отсутствии расходов получает по 20 единиц золота за раз. Это можно увидеть просматривая реплеи сражений, проведенных против сильного компьютера. К тому же, если посмотреть код ии, да и просто понаблюдать за поведением слабого компьютера и сильного/среднего, то можно заметить, что слабый бот начинает крипиться с задержкой, по сравнению со своими средней и сильной версиями. Сильный бот начинает апргейдить главное здание раньше, чем средний и слабый, следовательно, и исследования некоторые у него проходят раньше, второй/третий герой появляются раньше и здания соответствующие. Так же слабый не строит оборонительные сооружения на дополнительных рудниках. Как то так. К тому же, насколько я помню, слабый вроде бы вообще исследований не проводит. Ну и естественно, не всегда все работает в строгости с тем, как я описал и это верно не для всех ии, мое описание больше по ии Орды. Остальных помню плохо. Поведение ии зависит и от карты и от типов точек на ней и от того, как складывается сражение. Слабый ии вполне может обогнать по развитию среднего в некоторых случаях и так далее.
Сначала, Хоффман, думал обозвать тебя лентяем, но потом не удивился, почему ты ничего не нашел !!!
Близзарди засунули ети текстуры очень глубоко:
в архиве War3x.mpq есть архивы с названиями в виде букв английского алфавита, так вот твои заветние текстуры ето Cliff0.blp и Cliff1.blp в архиве Z.mpq.
quq_CCCP, пробовал, но что-то не получилось. вставил войска вокруг рудника, и рабы не могли войти в внутрь. Но это не из-за этого.
Все выяснил в чем дело.
нашел ответ
Сначала не понимал, почему вообще не хотело работать это. Везде тыкал, и проверял функцией, и дебагом выводил на экран. Абсолютно везде говорило, что можно передвигаться работникам (даже в воде).
Теперь врубился, почему так было. Нужно было создать блокиратор пути с PATHING_TYPE_PEONHARVESTPATHING. Было два варианта. Либо нарисовать "текстурку + декор" или через "триггеры". Хотя нарисовать текстуру в фотошопе как в статье xgm.guru/p/wc3/pathing-alternate мог, но не знал какого цвета, в статье не показано какого цвета тип PATHING_TYPE_PEONHARVESTPATHING. Или через триггеры см. карту xgm.guru/p/wc3/181384
Хотя создать блокиратор это было полбеды, нужно было понять почему не работает. Работники бегают по участку, то не бегают. Фиг поймешь. Этого можно было бы не заметить (в своей карте пришлось участок визуально рельефом приукрасить, чтобы мог отличать), чтобы понаблюдать. Потом заметил, что вурдалак неся срубленные деревья домой, начал обходить.
Работники когда идут добывать ресурсы, блокиратор их впускает (бывает и не хочет впускать). Но как только они добудут ресурсы, то получат приказ "resumeharvesting" и побегут домой. Тогда встречают в блок. И придется обходить участок. Правильно делают вурдалаки, хотя не всегда. А вот рабы орков и Альянса не правильные какие-то. Они встанут у границы, постоят 2-5 секунд. И походят у границы (туда-сюда), и находят как-будто бы "невидимую" щель, и все по одному входят.
Хотя это работает немного криво (у меня). Работники не хотят обходить участок, это раз. Во-вторых, работников могут впустить. то могут выпустить. Не понятно, что такое.
Насчет светлячков, их даже рассматривать не стал, так как добывают на одном месте.
Всем спасибо, проблему решил за счет проверки на цвет/номер игрока как индекс в массиве переменных. Все работает как запланировано.
Вопрос вдогонку: как можно задавать сам индекс переменной-массива?)
З.Ы. Массивы конечно зло, но другого способа хранить инфо по одному спеллу, не используя множество переменных - пока не умею.
Создаёт стену из магического льда, которая отталкивает противников от себя.
function IsUnitDeadBX takes unit u returns boolean
return GetUnitTypeId(u) == 0 or IsUnitType(u, UNIT_TYPE_DEAD)
endfunction
function IsTarget takes unit u,unit d returns boolean
return not IsUnitType(u,UNIT_TYPE_ANCIENT) and not IsUnitDeadBX(u) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) and (IsUnitEnemy(u, GetOwningPlayer(d)) or GetOwningPlayer(u) == Player(15))
endfunction
function SQ takes real xa, real ya, real xb, real yb returns real
return SquareRoot((xa-xb)*(xa-xb)+(ya-yb)*(ya-yb))
endfunction
function SafeX takes real pxx returns real
local real lfr=GetRectMinX(bj_mapInitialPlayableArea)+50
if(pxx<lfr)then
return lfr
endif
set lfr=GetRectMaxX(bj_mapInitialPlayableArea)-50
if(pxx>lfr)then
return lfr
endif
return pxx
endfunction
function SafeY takes real pyy returns real
local real lfr=GetRectMinY(bj_mapInitialPlayableArea)+50
if(pyy<lfr)then
return lfr
endif
set lfr=GetRectMaxY(bj_mapInitialPlayableArea)-50
if(pyy>lfr)then
return lfr
endif
return pyy
endfunction
function UBU takes unit u, unit d, unit c , real w returns boolean
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real r1 = 57.295827*Atan2(y-GetUnitY(d),x-GetUnitX(d))
local real r2 = 57.295827*Atan2(y-GetUnitY(c),x-GetUnitX(c))
set r2 = r2 -180
if r1 < 0.00 then
set r1 = r1 + 360
endif
if r2 < 0.00 then
set r2 = r2 + 360
endif
if r1 - r2 <= w and r1 - r2 >= -(w) then
return true
else
return false
endif
endfunction
function IceWallCon takes nothing returns boolean
return GetSpellAbilityId() == 'A0KP'
endfunction
function IceWallCreate takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
local unit c = LoadUnitHandle(udg_AssassinHash,id,0)
local real r = LoadReal(udg_AssassinHash,id,3)
local integer i = LoadInteger(udg_AssassinHash,id,4)
local integer j = LoadInteger(udg_AssassinHash,id,5)
local real x = LoadReal(udg_AssassinHash,id,StringHash("X"))
local real y = LoadReal(udg_AssassinHash,id,StringHash("Y"))
local real a = 0.
local real b = 0.
local boolean e = LoadBoolean(udg_AssassinHash,id,6)
local boolean f = LoadBoolean(udg_AssassinHash,id,7)
local boolean k = LoadBoolean(udg_AssassinHash,id,8)
local integer n = LoadInteger(udg_AssassinHash,id,25)
local real X2 = LoadReal(udg_AssassinHash,id,StringHash("X2"))
local real Y2 = LoadReal(udg_AssassinHash,id,StringHash("Y2"))
local real X3 = LoadReal(udg_AssassinHash,id,StringHash("X3"))
local real Y3 = LoadReal(udg_AssassinHash,id,StringHash("Y3"))
local integer h = 0
local group g = LoadGroupHandle(udg_AssassinHash,id,2)
local unit u
local unit d
local unit d1
if e == false then
set i = i+1
set j = j+1
if i < 7 then
set a = SafeX(x+(80.*i)*Cos(r))
set b = SafeY(y+(80.*i)*Sin(r))
set d = CreateUnit(GetOwningPlayer(c),'e00V',a,b,0)
call UnitAddAbility(d,'Arav')
call UnitRemoveAbility(d,'Arav')
call SetUnitFlyHeight(d,150,0)
call DestroyEffect(AddSpecialEffect("FrozenOrbBall.mdx",a,b))
call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl",a,b))
call SaveUnitHandle(udg_AssassinHash,id,StringHash("IWU1"+I2S(i)),d)
set a = SafeX(x-(80.*j)*Cos(r))
set b = SafeY(y-(80.*j)*Sin(r))
set d = CreateUnit(GetOwningPlayer(c),'e00V',a,b,0)
call UnitAddAbility(d,'Arav')
call UnitRemoveAbility(d,'Arav')
call SetUnitFlyHeight(d,150,0)
call DestroyEffect(AddSpecialEffect("FrozenOrbBall.mdx",a,b))
call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl",a,b))
call SaveUnitHandle(udg_AssassinHash,id,StringHash("IWU2"+I2S(j)),d)
call SaveInteger(udg_AssassinHash,id,4,i)
call SaveInteger(udg_AssassinHash,id,5,j)
else
call SaveBoolean(udg_AssassinHash,id,6,true)
endif
else
if f == false then
call SaveInteger(udg_AssassinHash,id,4,0)
call SaveReal(udg_AssassinHash,id,3,r-1.566)
call TimerStart(t,.025,true,function IceWallCreate)
call SaveBoolean(udg_AssassinHash,id,7,true)
else
set i = i+1
if i < 201 then
call SaveInteger(udg_AssassinHash,id,4,i)
set d = LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU16"))
set d1 = LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU26"))
call GroupClear(udg_G)
call GroupEnumUnitsInRange(udg_G,x,y,1040,null)
loop
set u = FirstOfGroup(udg_G)
if IsTarget(u,c) and UBU(u,d,d1,20.) and IsUnitInGroup(u,g) == false then
call GroupAddUnit(g,u)
if GetUnitAbilityLevel(c,'B009') > 0 then
call UnitDamageTarget(c,u,150.+80.*GetUnitAbilityLevel(c,'A0KP'),true,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,null)
else
call UnitDamageTarget(c,u,75.+40.*GetUnitAbilityLevel(c,'A0KP'),true,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,null)
endif
set n = n+1
call SaveInteger(udg_AssassinHash,id,25,n)
call SaveInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(n)),15)
if SQ(X3,Y3,GetUnitX(u),GetUnitY(u)) > SQ(X2,Y2,GetUnitX(u),GetUnitY(u)) then
call SaveReal(udg_AssassinHash,id,StringHash("IWR"+I2S(n)),LoadReal(udg_AssassinHash,id,20))
else
call SaveReal(udg_AssassinHash,id,StringHash("IWR"+I2S(n)),LoadReal(udg_AssassinHash,id,21))
endif
call SaveUnitHandle(udg_AssassinHash,id,StringHash("IWU"+I2S(n)),u)
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\FrostArrows\\NagaColdArrowMissile.mdl",u,"chest"))
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl",u,"chest"))
endif
call GroupRemoveUnit(udg_G,u)
exitwhen u == null
endloop
set i = 1
if n > 0 then
loop
exitwhen i > n
set h = LoadInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(i)))-1
set r = LoadReal(udg_AssassinHash,id,StringHash("IWR"+I2S(i)))
set u = LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU"+I2S(i)))
call SaveInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(i)),h)
call SetUnitPathing(u,false)
call SetUnitX(u,SafeX(GetUnitX(u)+15.*Cos(r)))
call SetUnitY(u,SafeY(GetUnitY(u)+15.*Sin(r)))
call IssueImmediateOrder(u,"stop")
if ModuloInteger(h,3) == 0 then
call DestroyEffect(AddSpecialEffectTarget("FrozenOrbBall.mdx",u,"chest"))
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl",u,"chest"))
endif
set i = i + 1
endloop
set i = 1
loop
exitwhen i > n
set h = LoadInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(i)))
set u = LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU"+I2S(i)))
if h <= 0 or IsUnitDeadBX(u) or not IsTarget(u,c) then
set j = i
call GroupRemoveUnit(g,u)
call SetUnitPathing(u,true)
loop
exitwhen j > n
call SaveReal(udg_AssassinHash,id,StringHash("IWR"+I2S(j)),LoadReal(udg_AssassinHash,id,StringHash("IWR"+I2S(j+1))))
call SaveInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(j)),LoadInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(j+1))))
call SaveUnitHandle(udg_AssassinHash,id,StringHash("IWU"+I2S(j)),LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU"+I2S(j+1))))
set j = j + 1
endloop
set n = n-1
call SaveInteger(udg_AssassinHash,id,25,n)
endif
set i = i + 1
endloop
endif
else
set i = 1
if n > 0 then
loop
exitwhen i > n
set h = LoadInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(i)))-1
set r = LoadReal(udg_AssassinHash,id,StringHash("IWR"+I2S(i)))
set u = LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU"+I2S(i)))
call SaveInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(i)),h)
call SetUnitPathing(u,false)
call SetUnitX(u,SafeX(GetUnitX(u)+15.*Cos(r)))
call SetUnitY(u,SafeY(GetUnitY(u)+15.*Sin(r)))
call IssueImmediateOrder(u,"stop")
if ModuloInteger(h,3) == 0 then
call DestroyEffect(AddSpecialEffectTarget("FrozenOrbBall.mdx",u,"chest"))
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl",u,"chest"))
endif
set i = i + 1
endloop
set i = 1
loop
exitwhen i > n
set h = LoadInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(i)))
set u = LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU"+I2S(i)))
if h <= 0 or IsUnitDeadBX(u) then
set j = i
call GroupRemoveUnit(g,u)
call SetUnitPathing(u,true)
loop
exitwhen j > n
call SaveReal(udg_AssassinHash,id,StringHash("IWR"+I2S(j)),LoadReal(udg_AssassinHash,id,StringHash("IWR"+I2S(j+1))))
call SaveInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(j)),LoadInteger(udg_AssassinHash,id,StringHash("IWI"+I2S(j+1))))
call SaveUnitHandle(udg_AssassinHash,id,StringHash("IWU"+I2S(j)),LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU"+I2S(j+1))))
set j = j + 1
endloop
set n = n-1
call SaveInteger(udg_AssassinHash,id,25,n)
endif
set i = i + 1
endloop
endif
if k == false then
set j = 1
loop
exitwhen j > 6
set d = LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU1"+I2S(j)))
call DestroyEffect(AddSpecialEffect("FrozenOrbBall.mdx",GetUnitX(d),GetUnitY(d)))
call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl",GetUnitX(d),GetUnitY(d)))
call KillUnit(d)
set j = j + 1
endloop
set j = 1
loop
exitwhen j > 6
set d = LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU2"+I2S(j)))
call DestroyEffect(AddSpecialEffect("FrozenOrbBall.mdx",GetUnitX(d),GetUnitY(d)))
call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl",GetUnitX(d),GetUnitY(d)))
call KillUnit(d)
set j = j + 1
endloop
set d = LoadUnitHandle(udg_AssassinHash,id,StringHash("IWU"))
call KillUnit(d)
call DestroyEffect(AddSpecialEffect("FrozenOrbBall.mdx",GetUnitX(d),GetUnitY(d)))
call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl",GetUnitX(d),GetUnitY(d)))
call SaveBoolean(udg_AssassinHash,id,8,true)
endif
if k and n <= 0 then
call DestroyGroup(g)
call DestroyTimer(t)
call FlushChildHashtable(udg_AssassinHash,id)
endif
endif
endif
endif
set t = null
set c = null
set d = null
set d1 = null
set g = null
set u = null
endfunction
function IceWall takes nothing returns nothing
local unit c = GetSpellAbilityUnit()
local real a = GetUnitX(c)
local real b = GetUnitY(c)
local real x = SafeX(GetSpellTargetX())
local real y = SafeY(GetSpellTargetY())
local real r = Atan2(y-b,x-a)+1.566
local timer t = CreateTimer()
local real dist = SQ(a,b,x,y)*2.
local integer id = GetHandleId(t)
local unit d
set d = CreateUnit(GetOwningPlayer(c),'e00V',x,y,0)
call UnitAddAbility(d,'Arav')
call UnitRemoveAbility(d,'Arav')
call SetUnitFlyHeight(d,150,0)
call SaveUnitHandle(udg_AssassinHash,id,StringHash("IWU"),d)
call DestroyEffect(AddSpecialEffect("FrozenOrbBall.mdx",x,y))
call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl",x,y))
call SaveUnitHandle(udg_AssassinHash,id,0,c)
call SaveReal(udg_AssassinHash,id,3,r)
set r = Atan2(y-b,x-a)
call SaveReal(udg_AssassinHash,id,20,r)
call SaveReal(udg_AssassinHash,id,21,Atan2(b-y,a-x))
call SaveReal(udg_AssassinHash,id,StringHash("X2"),a+dist*Cos(r))
call SaveReal(udg_AssassinHash,id,StringHash("Y2"),b+dist*Sin(r))
call SaveReal(udg_AssassinHash,id,StringHash("X3"),a)
call SaveReal(udg_AssassinHash,id,StringHash("Y3"),b)
call SaveGroupHandle(udg_AssassinHash,id,2,CreateGroup())
call SaveReal(udg_AssassinHash,id,StringHash("X"),x)
call SaveReal(udg_AssassinHash,id,StringHash("Y"),y)
call TimerStart(t,.025,true,function IceWallCreate)
set t = null
set c = null
set d = null
endfunction
JackFastGame, старый знакомый баг с каналом из доты, лекарство только одно применять для канала ID приказа которых больше не будет ни у 1 юнита, или все способности ID приказа которых ты копируешь для канала, должны появится у юнитов и быть применены до того как твои герои выучат способность на основе канала.
Движок вара кеширует приказ и тип цели для этого приказа, поэтому триггерно невозможно отдать приказ, у него по мнению движка другой тип цели.
Нельзя применить высасывание жизни на юнита, потому что записано что для этого приказа не требуется цель...
Подробности можно спросить у DracoL1ch.
Самый простой алгоритм - для каждого юнита-цели создаешь даммик (Юнит со способностью москиты 'Aloc', без модели, тени и с отключенной атакой), который, получив нужный приказ, радостно кидает корни с нужными параметрами в оную цель. Не забудь применить к даммику ограничение времени жизни, чтобы он скастовал и благополучно сдох.
Герою же просто выдаешь пустышку на основе нейтрально-враждебной геройской способности Канал, срабатывание которой и отлавливаешь триггером, делающим вышеуказанные действия.
После того, как кнопка была нажата, создавай даммика и заставляй его оплетать рудник.
Нет нужды, близзард.ж помощь (для справки, там есть функция которая сразу же сменяет обычный рудник на проклятый, рядом с исходной позицией игрока ) Если вы делайте мили карту, то вам могут очень пригодится и другие функции из Blizzard.j, советую с ними ознакомится.
В самом лобби так сделать нельзя. Можно лишь через расу и гандикап, как сделан какой-то мод на варик, добавляющий расы. При старте карты проверяешь расу, выбранную игроком и его гандикап (50-90 %), а затем спавнишь заранее прописанных стартовых юнитов, как и предложил предыдущий комментатор.
а если просто вывести диалоговое окно и проверить кнопку и триггерно выдать базу?
bazeba, чтобы мазохисты могли убирать часть утечек и таким образом и дальше заниматься мазохизмом
там ещё точка утекает
Position of () создаёт точку которая утекает
Делай мвссив с индексом равным номеру игрока (чтоб не запутаться) При событии ставь условие на триггеринг игрока. Если триггенинг игрок = красный то перекидывай соотв. юнита по индексу. напр MyHero[1]. Используй if then else. Все вместится в 1 триггер с кол-вом событий равным кол-ву игроков.
Cancel, тогда ручками правь j файл
это единственный способ обойтись без джнгп
и вроде в джнгп есть директива для отключения джассхелпера?
т.е. по идее 1,29 должен работать
и что ты там учить для джнгп такое сложно собрался?
он запускается точно так же как и обычный редактор
Юзай поиск. Нейтральный игроки не дают полноценной возможности управлять ихними юнитами, и поэтому приходится в константах рыться либо костыли (с приказами). Кроме возврата там у них есть много чего другого: например крип игнорит башню, идет мимо нее и др.
awesomesk1ll, короче я задолбался и тупо сделал проверку на угол поворота атакующего там где угол атакуемого 315-0-45 без всяких вычитаний, иного способа видимо нет ибо из-за чисел 315-360 и 0-45 все летело ко дну
это немного не то но пох уже просто реально все достало)
К сожалению, таким способом будут работать только башни, улучшенные до Башни Стрелка во время игры. Если изначально на карте стоят Башни Стрелки, они работать не будут. Если надо могу исправить.
Исправил. Теперь Башни Стрелки, поставленные на карту в редакторе будут работать так же, как те, что были улучшены во время игры.
Берем основную модель, возможно, вообще без мяса, только с гусеницами, но с кучей точек крепления. Также берем кучу моделей-аттачметов, представляющих собой эти самые пушки, корпуса и все прочее. При выборе характеристик модели через диалог или интерфейс соответственно создаем на основной модели эффекты-аттачменты, будет собрана техника. Такие штуки, как двигатель и прочие невидные извне элементы будут скорее входить в математическую модель юнита, но это также можно запилить. Название танка - сразу не скажу, есть ли триггер на смену, но на таблице рекордов можно отобразить что угодно.
2.Тоже можно.
Создаем погодный в определенной местности и делаем два триггера для контроля входа-выхода юнитов из нее. На искомых юнитов применяем нужные способности - и все готово.
Здесь чуть сложнее: нужно постоянно проверять тип местности под юнитом, но тоже можно. Проверка на ограждения тоже может бить сделана.
4.Это уже интереснее. Видел раньше подобное в играх. При каждой атаке юнита случайным образом наносим или не наносим доп. урон, эффект горения, кидаем спелл на цель в зависимости от теоретического места попадания атаки.
5.И это можно. Но нужно писать нестандартную систему Альянса. Но через триггеры и JASS все можно...
Продажа техники - лучше через способность, что бы кидать ее на понравившегося юнита, не стоит покупать кота в мешке. Стоимость должна зависеть от технического уровня юнита, его текущего состояния (мертвый танк попадет вам бесплатно, сами чините!), если он был модернизован дополнительно, то это тоже входит в стоимость. Разрешение на продажу делаем аналогично.
Это легко через Custom Value и переменние.
Как ты понял, все что ты предложил создать можно, но на это нужно потрать хороший кусок времени. Остается пожелать тебе удачи над созданием проекта - мне идея уже нравится.
отменять постройку юнита если технология уже ап
либо как сразу говорили через ап здания
где каждому твоему зданию будет соответствовать такое же здание но с дополнительным слотом
с продажей юнита открываешь доту и смотришь как там сделан спелл передать предметы у куры
он сделан как раз через продажу юнита
иначе никак
если не нравится пожалуйся богу об этом
или близардам
пусть выпустят новый патч специально для тебя
Это просто гуглится. А ещё можно открыть близовскте карты и скопипастить оттуда.
Самый банальный способ.
В Редакторе Объектов ставишь своей башни Point Value равное стоимости башни. Даёшь башне способность Х на основе Channel (Канал).
А теперь триггер.
События:
Юнит начинает применять способность.
Условия:
Тип юнита равно Здание
Применяемая способность равно Х
Действие:
Add Integer(0.70 x (Real(Point Value of Casting Unit))) to (Owner of Casting Unit) Current Gold
Удалить Casting Unit
Кто-нибудь, переведите части на английском на русский, я не пользуюсь русской версией редактора.
Smart096, баг только в этой карте?
в новых картах бага нету?
если да то стоит проверить импортируемые модели и текстуры (мб часть битая)
но с вероятностью в 60% проблема в системе ибо было много жалоб на баги в вин10
Наверное скорее проблема в версии что плагина что макса ну поробуй другую версию макса с 2011-2014 и точно убедись что плагин именно под твою версию.
Наверное закрывай тему так как знатаков макса здесь не очень много.
Absolute, есть событие загрузки игры, можешь поставить там логическая_переменная=Да, а в действиях с удалением молнии поставить Если/То/Иначе, где Если условие логическая_переменная=Нет, То удалить молнию, Иначе ничего не делать
Правильный ответ назвали - отрубается main по причине лимита вызовов, нужно триггеры с событием инициализация карты делать отсроченными таймером, либо действительно executefunc.
Я уже плохо помню и не уверен, что сработает, но попробуй некоторые события инициализации заменить на "прошло 0.01 сек" или вроде того.
Нужна переменная, в которой хранить уже добавленное золото, чтобы не добавлять лишнего - изначально 0.
Каждые х сек, вычислять разницу между "Золота добыто" и этой переменной. Затем разницу добавлять к переменной и к золоту игрока.
Т.е. если триггер сработает после первых 5-и рабов, то даст 50 золотых.
Затем если перед следующим срабатыванием еще 2 раба принесут по 10 золота, то "Золото добыто" станет 70, а в переменной у нас 50 - триггер добавит еще 20 золота.
Ну как бы там все одно да потому, код тот же что я описал выше, вот только проверять все надо в МУИ это раз, два время затраченное на синхронизацию может быть пипец каким большим...
function Trig_SyncStr_Actions takes nothing returns nothing
local string splayer = null
local player pl = Player(0)
if GetLocalPlayer() == pl then
call StoreString( udg_Data, "A", "B", "твоя строка!" )
endif
call TriggerSyncReady()
if GetLocalPlayer) == pl then
call SyncStoredString( udg_Data, "A", "B" )
endif
call TriggerSleepAction( 2.00 )
call TriggerSyncReady()
set splayer = GetStoredString( udg_Data, "A", "B" ) // выгрузи строку из кеша в локалку и делай с ней что хочешь
endfunction
//===========================================================================
function InitTrig_SyncStr takes nothing returns nothing
set gg_trg_SyncStr = CreateTrigger( )
call TriggerAddAction( gg_trg_SyncStr, function Trig_SyncStr_Actions )
endfunction
Триггер запускаем ExecuteTrigger а "Твоя строка" заменяется на глобальную переменную.
Как объединить зелья лечения в одно с зарядом, если герой имеет одно в инвентаре и поднимает второе?
обычно используют "событие - юнит получает предмет", И на предмет, который вы получаете, ссылается переменная, которая называется item being manipulated. А юнит, который получает итем - Triggering Unit. Вы можете с помощью этой переменной итема узнать тип, сравнить. Потом циклом пробегаете по слотам (от 1 до 6), тут вся суть в одной команде триггерной (item in slot X, итем в слоте Х) и проверяете есть ли такой же итем (не забываем делать проверки, на то что этот предмет не равен item being manipulated и сравниваете не одинаковые ли типы). Если есть такой же (находите тот же тип что и item being manipulated), то от item being manipulated берете заряды и прибавляете к зарядам существующего, а потом item being manipulated удаляете. Недостаток: при заполненном инвентаре такая штука не будет работать.Не хватает свободного места.
код
цикл А от 1 до 6
if тип итема (item being manipulated) РАВНО тип итема (item in slot А) and item being manipulated НЕ РАВНО item in slot А then проверяете
set k = Charges remaining in ( item being manipulated) + Charges remaining in ( item in slot А) складываете заряды
Set charges remaining in ( item in slot А) to ( k) устанавливаете кол-во зарядов
Remove Item (item being manipulated) удаляете
endif
Есть гуишная проверка на наличие итема определенного типа в инвентаре, но она утечна. И лучше циклом прогонять.
Кстати выше пример, там вот дропают итем, зачем? чтобы проверить есть ли такой же итем. А то мб проверка на наличие итема определенного типа в инвентаре найти подобранный итем. А нам нужно знать, что есть еще один, кроме подобранного. Поэтому дропают. Только не понятно зачем создаете новый итем.
Проверка, на то что подобранный предмет имеет зарядов больше 0, говорит нам о том что это не обычный предмет.
есть статьи
Как зелье с зарядом разделить, если игрок перекладывает зелье с зарядом в другую ячейку инвентаря, если возможно, то разделение происходить должно только при нажатии какой-то клавиши?
можно перекладывать в другой слот. для этого ловят приказ. Короче смотрите системы CCS
там создают новый такой же предмет, и выделяют кол-во зарядов, деля поровну например. Абилкой например, попробуй сделать целевую активную абилку с целью предмет, указывай на инвентарь и дели.
Как это можно сделать покороче для множества разных типов предметов?
всмысле покороче? сделать под одну группу? есть же классификация. Я вот делаю так, что все предметы, которые с зарядами, должны иметь классификацию "с зарядами". Не помню точно как называется класс итемов.
Как правильно реализовать в инвентаре 7 слот?
если у героя заполнен инвентарь, то он может подобрать руну. Вот в доте система скрещивания. То же самое можно сделать и с зарядами. На земле у него лежат руны, при подборе руна исчезает. Но мы проверяем слоты, есть ли такой итем. Если есть, прибавляем заряды к существующему. Иначе создать новый. При дропе итема, оригинал подменяет снова на руну. В руну можно передать значения зарядов.
А также ограничения какие-то на количество зарядов нужно ставить или сама система выше какой-то планки не даст собирать?
до такого не доходил.
скинул примеры (хотя многие дурацкие, но делал здесь хгм в качестве ответов)
вот еще одна система hh
Ну делать триггерную версию иллюзий, ибо придется создавать иллюзии жезлом иллюзий, ну а так же лепить спецэффект с помощтью юнитов снарядов.
Я как то делал кастомный аналог иллюзий мастера клинка. Там все просто, скрываем кастера и его клонов а на его место создаем спецэффект и даммики-снаряды, чтобы сделать спецэффект. У дефолтной mirror image - скорость снаряда 1150 ед.\сек. а дальность полета 150.
Какой точный вопрос, однако.
Ответ: триггерно, либо в редакторе объектов, если нужно изменить характеристики, не создаваемые/изменяемые триггерно.
Попытаюсь сыграть в экстрасенса, подстрахуюсь логикой:
Если нужно, чтобы изменялась характеристика количественно, т.е, например, увеличивался наносимый урон, то в действии нанесения урона вместо точного значения нужно выставить функию (формулу, зависимость etc.) имеющую аргументом уровень способности.
Если нужно менять характеристику качественно, например, тип наносимого урона, то следует использовать условия, сравнивающие уровень способности с нужным значением и... далее есть несколько вариантов реализации, но наиболее подходящий - просто выполнять все последующие действия триггера внутри оператора, а затем создать несколько раз скопировать его для других условий. Хотя, с точки зрения программирования, это не очень хороший вариант.
Pick every unit in range [250] matching condition [бафф спелла]
Всё что находится внутри данного блока произойдёт столько раз, сколько воинов находится внутри выбранной группы. Обратиться к воину можно через Picked Unit ( GetEnumUnit( ) ). Если Вам нужно добавить событие на смерть именно этих воинов, то прямо здесь внутри блока добавляете их в событие триггера, выбрав их через Picked Unit, или сохраняете их в переменные.
Также можно не сохранять каждого воина, а занести их в отдельную группу. А вместо проверки:
Собственные попытки в студию, что не получается?
Напомним - ЭТО НЕ СТОЛ ЗАКАЗОВ, здесь задают вопросы про реализацию тех или иных вопросов, спрашивают про ошибки, оптмизацию, отдельные функции. Я не увидел в вашем вопросе ничего кроме невнятного описания механики способности, " вокргу кого то там огненные столбы возникают, и еще порча"...
Filius Dei, во вредные советы подъехали...
Русификатор очень поможет тем кто собрался ломануть чужую карту и сделать её мод, прям ваще жир...
Потом нубам вроде сударя не стоит бежать ломать чужую карту, чето там пытатся копировать - это все бесполезно, недавно был похожий вопрос - помогите взломать карту за вознаграждение, карту сломали - ну а дальше что? Он неспособен ничего сделать потому что просто не понимает как?
Играя в некую карту вы мните себя великими балансерами и картоделами, мол да чё там, шяс подправлю пару значений и все будет норм - нет не будет, это не так просто как может показаться, без понимания устройства карты и знания Jass вам нечего там делать, вы тупо ничего не сможете изменить, да даже скопировать и вставить!
Помните что без труда не выловишь и рыбку из пруда, т.е изи способов в 1 кнопку взять и запилить чужую карту так как вам хочется или вдруг стащить всех героев себе в карту нет, а уж теболее не случится так что вам кто то возьмет и все это сделает вам за спасибо...
Любая строка ограничена, 256 символов латиницы и вдвое меньше символов кирилицы насколько я помню.
Никак не лечится, краткость сестра таланта и все такое.
имеет смысл открыть раздел ГУИ с плавающим текстом, взять словарик английского и самому попробовать его различные комбинации. Если ответить вкратце - да, это можно сделать
Floating Text - Create floating text that reads (Текст) above DamageEventTarget with Z offset (40.00 + (Random real number between 1.00 and 25.00)), using font size 13.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency - создает надпись Текст с нужными настройками цвета и смещения по оси Z над нужным нам юнитом. Создавать текст также можно в любой точке
Floating Text - Set the velocity of (Last created floating text) to 75.00 towards 90.00 degrees - Текст будет смещен на 75 ед. с углом смещения 90 градусов
Floating Text - Change (Last created floating text): Disable permanence - не помню, что делает
Floating Text - Change the lifespan of (Last created floating text) to 3.50 seconds - устанавливает время жизни текста 3,5 сек
Floating Text - Change the fading age of (Last created floating text) to 1.40 seconds - заставляет текст медленно гаснуть в течении 1,4 сек, чтобы он не пропадал резко и выглядело красиво
В помощь тебе библиотеки(library) и базы данных.
Либы — для обращения по виду library_name.functionName(arguments)
Базы данных — для выделения юниту своих переменных.
С БД может быть момент не совсем понятным, поэтому скидываю пример:
Эта порнография разработана для личного пользования
У меня в коде есть иллюзия использования вжасса. Либа просто для доп табуляции и невостребованых манипуляций на случай импорта. При создании юнита ему присваивается ряд переменных, а номер этих переменных, относящихся к этому юниту, записывается в его(юнита) UnitUserData
library UnitDataBase
globals
constant integer UnitDBSize = 512
constant integer UnitDBHeroesStart = 0
constant integer UnitDBHeroesUnder = 49
constant integer UnitDBUnitsStart = 50//Includes illusions of heroes. Or Should include them at least :P
constant integer UnitDBUnitsUnder = 319
constant integer UnitDBSummonsStart = 320
constant integer UnitDBSummonsUnder = 511
integer UnitDBNextHero = 0
integer UnitDBNextUnit = 50
integer UnitDBNextSummon = 320
unit array UnitDBUnit[UnitDBSize]
real array UnitDBCurrentAnimationSpeed[UnitDBSize]
unit array UnitDBForceAttackTarget[UnitDBSize]
integer array UnitDBAffectedByStuns[UnitDBSize]
real array UnitDBMagicResistance[UnitDBSize]
real array UnitDBPhysResistance[UnitDBSize]
real array UnitDBCurrentArmor[UnitDBSize]//This armor does not include agility bonuses. Not used yet :>
real array UnitDBWhiteMovementSpeed[UnitDBSize]
real array UnitDBCurrentCustomSlow[UnitDBSize]
real array UnitDBMagicDamageAmplifier[UnitDBSize]
real array UnitDBPhysDamageAmplifier[UnitDBSize]
real array UnitDBAdditionalHealth[UnitDBSize]//AKA Shield. Healed whenever unit takes damage.
constant real GravityAcceleration = 14.//Azeroth, bitch!
real array UnitDBFlyingHeight[UnitDBSize]//Not used yet
real array UnitDBFallingSpeed[UnitDBSize]
integer array UnitDBItemUseVariable[UnitDBUnitsStart]//just don't ask
item array UnitDBLastUsedItem[UnitDBUnitsStart]
real array UnitDBCastPointX[UnitDBUnitsStart]
real array UnitDBCastPointY[UnitDBUnitsStart]
integer UnitDBPreviousHero//Used for exitwhen event. Its next minus two.
unit array UnitDBHeroHPBar[UnitDBUnitsStart]
unit array UnitDBHeroMPBar[UnitDBUnitsStart]
unit array UnitDBHeroSPBar[UnitDBUnitsStart]
endglobals
//Больно жирные для инлайна
function UnitDBFindNextFreeVariable takes integer i returns integer
local unit u
loop
set u = UnitDBUnit[i]
exitwhen u == null or GetUnitTypeId( u ) < 1
set i = i + 1
endloop
set u = null
return i
endfunction
function UnitDBAddHero takes unit u, real mdef, real armor returns nothing
local integer i = UnitDBNextHero
local real x = GetUnitX(u)
local real y = GetUnitY(u)
call UnitMakeAbilityPermanent( u, true, 'A00B' )
set UnitDBUnit[i] = u
call SetUnitUserData( u, i )
call GroupAddUnit( UnitsInPlayableArea, u )
set UnitDBItemUseVariable[i] = 0
set UnitDBCurrentAnimationSpeed[i] = 0.
set UnitDBAffectedByStuns[i] = 0
set UnitDBMagicResistance[i] = mdef
set UnitDBCurrentArmor[i] = armor
set UnitDBWhiteMovementSpeed[i] = GetUnitDefaultMoveSpeed( u )
set UnitDBCurrentCustomSlow[i] = 1.
set UnitDBMagicDamageAmplifier[i] = 1.
set UnitDBPhysDamageAmplifier[i] = 1.
set UnitDBFlyingHeight[i] = 0.//Doesn't include point height.
set UnitDBAdditionalHealth[i] = 0.
/*if ( i == UnitDBHeroesUnder ) then
call BJDebugMsg("|c00ff6060Hero limit reached! More heroes can be created, but things can go wild.")
endif*/
set UnitDBNextHero = i + 1
set UnitDBPreviousHero = i - 1
set UnitDBHeroHPBar[i] = CreateUnit(BossPlayer1, 'hmil', x, y, 0. )
call SetUnitAnimationByIndex( UnitDBHeroHPBar[i], 100 )
set UnitDBHeroMPBar[i] = CreateUnit( BossPlayer1, 'hrtt', x, y, 0. )
call SetUnitAnimationByIndex( UnitDBHeroMPBar[i], 100 )
set UnitDBHeroSPBar[i] = CreateUnit( BossPlayer1, 'hwt2', x, y, 0. )
call SetUnitAnimationByIndex( UnitDBHeroSPBar[i], 0 )
set u = null
return
endfunction
function UnitDBAddUnit takes unit createdUnit, real mdef, real armor returns nothing
local integer i = UnitDBNextUnit
local unit u = UnitDBUnit[i]
if ( u == null ) then
set i = UnitDBFindNextFreeVariable( UnitDBSummonsStart )
endif
set UnitDBUnit[i] = createdUnit
call SetUnitUserData( createdUnit, i )
call GroupAddUnit( UnitsInPlayableArea, createdUnit )
set UnitDBCurrentAnimationSpeed[i] = 0.
set UnitDBAffectedByStuns[i] = 0
set UnitDBMagicResistance[i] = mdef
set UnitDBCurrentArmor[i] = armor
set UnitDBWhiteMovementSpeed[i] = GetUnitDefaultMoveSpeed( createdUnit )
set UnitDBCurrentCustomSlow[i] = 1.
set UnitDBMagicDamageAmplifier[i] = 1.
set UnitDBPhysDamageAmplifier[i] = 1.
set UnitDBFlyingHeight[i] = 0.
set UnitDBAdditionalHealth[i] = 0.
if ( i < UnitDBSummonsUnder) then
set UnitDBNextSummon = i + 1
else
set UnitDBNextSummon = UnitDBSummonsStart
endif
set u = null
set createdUnit = null
return
endfunction
function UnitDBAddSummon takes unit summonedUnit, real mdef, real armor returns nothing
local integer i = UnitDBNextSummon
local unit u = UnitDBUnit[i]
if ( u == null ) then
set i = UnitDBFindNextFreeVariable( UnitDBSummonsStart )
endif
set UnitDBUnit[i] = summonedUnit
call SetUnitUserData( summonedUnit, i )
call GroupAddUnit( UnitsInPlayableArea, summonedUnit )
set UnitDBCurrentAnimationSpeed[i] = 0.
set UnitDBAffectedByStuns[i] = 0
set UnitDBMagicResistance[i] = mdef
set UnitDBCurrentArmor[i] = armor
set UnitDBWhiteMovementSpeed[i] = GetUnitDefaultMoveSpeed( summonedUnit )
set UnitDBCurrentCustomSlow[i] = 1.
set UnitDBMagicDamageAmplifier[i] = 1.
set UnitDBPhysDamageAmplifier[i] = 1.
set UnitDBFlyingHeight[i] = 0.
set UnitDBAdditionalHealth[i] = 0.
if ( i < UnitDBSummonsUnder) then
set UnitDBNextSummon = i + 1
else
set UnitDBNextSummon = UnitDBSummonsStart
endif
set u = null
set summonedUnit = null
return
endfunction
//Система маг резиста была изменена на дефолтную, была введена аналогичная ей система физ урона.
//Необходимо протестить эти системы на низких значениях. (могучий float и его точность). В нынешних условиях низкие значения не достигаются. На тест положен болт. Есть нерешенные проблемы с точностью(при восстановлении, опять же, резисты съезжают). Необходимо учитывать при вычислениях лишь первые три цифры после запятой, например.
#define UnitDBIncreaseUnitMagicResistance( amount, userData ) = {
set UnitDBMagicResistance[userData] = UnitDBMagicResistance[userData] * amount
}
#define UnitDBDecreaseUnitMagicResistance( amount, userData ) = {
set UnitDBMagicResistance[userData] = UnitDBMagicResistance[userData] / amount
if ( UnitDBMagicResistance[userData] > 0.99997 and UnitDBMagicResistance[userData] < 1.00003 ) then
set UnitDBMagicResistance[userData] = 1.
endif
}
#define UnitDBIncreaseUnitPhysResistance( amount, userData ) = {
set UnitDBPhysResistance[userData] = UnitDBPhysResistance[userData] * amount
}
#define UnitDBDecreaseUnitPhysResistance( amount, userData ) = {
set UnitDBPhysResistance[userData] = UnitDBPhysResistance[userData] / amount
if ( UnitDBPhysResistance[userData] > 0.99997 and UnitDBPhysResistance[userData] < 1.00003 ) then
set UnitDBPhysResistance[userData] = 1.
endif
}
#define UnitDBReplaceUnitMagicResistance( before, after, userData ) = {
set UnitDBMagicResistance[userData] = UnitDBMagicResistance[userData] / before * after
}
#define UnitDBReplaceUnitPhysResistance( before, after, userData ) = {
set UnitDBPhysResistance[userData] = UnitDBPhysResistance[userData] / before * after
}
#define UnitDBIncreaseUnitMagicDamageAmplifier( amount, userData ) = {
set UnitDBMagicDamageAmplifier[userData] = UnitDBMagicDamageAmplifier[userData] + amount
}
#define UnitDBDecreaseUnitMagicDamageAmplifier( amount, userData ) = {
set UnitDBMagicDamageAmplifier[userData] = UnitDBMagicDamageAmplifier[userData] - amount
if ( UnitDBMagicDamageAmplifier[userData] > 0.99997 and UnitDBMagicDamageAmplifier[userData] < 1.00003 ) then
set UnitDBMagicDamageAmplifier[userData] = 1.
endif
}
#define UnitDBIncreaseUnitPhysDamageAmplifier( amount, userData ) = {
set UnitDBPhysDamageAmplifier[userData] = UnitDBPhysDamageAmplifier[userData] + amount
}
#define UnitDBDecreaseUnitPhysDamageAmplifier( amount, userData ) = {
set UnitDBPhysDamageAmplifier[userData] = UnitDBPhysDamageAmplifier[userData] - amount
if ( UnitDBPhysDamageAmplifier[userData] > 0.99997 and UnitDBPhysDamageAmplifier[userData] < 1.00003 ) then
set UnitDBPhysDamageAmplifier[userData] = 1.
endif
}
#define UnitDBIncreaseUnitShield( amount, userData ) = {
set UnitDBAdditionalHealth[userData] = UnitDBAdditionalHealth[userData] + amount
//redraw
}
#define UnitDBDecreaseUnitShield( amount, userData ) = {
set UnitDBAdditionalHealth[userData] = UnitDBAdditionalHealth[userData] - amount
if ( UnitDBAdditionalHealth[userData] < 0. ) then//Perhaps should be typed manually on every use. No need of that atm.
set UnitDBAdditionalHealth[userData] = 0.
endif
//redraw
}
function UnitDBAddUnitsCreatedOnInit takes nothing returns nothing
local unit u = GetEnumUnit()
if ( not IsUnitType( u, UNIT_TYPE_HERO ) ) then
call UnitDBAddUnit( u, 1., 0. )//!!! whatever
endif
set u = null
return
endfunction
endlibrary
Во внутреннем представлении (читай: "после отработки препроцессора JassHelper") любая структура есть набор массивов с индексом, по которому лежат данные именно этой структуры во всех связанных массивах. По факту, передавая структуру в качестве аргумента функции, ты передаёшь только её id из массива.
По поводу вопроса: полного перевода vJass мануала на русский язык не существует в природе, так что вот ссылка на английский: www.wc3c.net/vexorian/jasshelpermanual.html Крайне рекомендую пользоваться не базовым синтаксисом, а C-подобным, который обеспечивает "AdicHelper" aka cJass (ссылка на русскую версию мануала), это позволит в будущем гораздо проще перейти к программированию на полноценных языках.
да вот только thistype возвращает структуру из которой он вызван, а не структуру инстанса идентификатора, т.е. getTrack будет всегда возвращать тип Tracker. Вопрос в том, как по идентификатору определить конкретный тип структуры и к нему привести.
Этот код тестировал? Он должен работать.
Структуры в vJass - массивы. Объект структуры - integer.
У каждой структуры есть массив, куда записывается тип каждого объекта структуры. Пусть у Trackle айди 1, а у Button 2. При создании объекта структуры будет сделано следующее: set массив_куда_записывается_тип[объект_структуры] = айди_структуры. При создании объекта Button и в массив типа структуры Button, и в массив структуры Trackle будет записано 2.
Перезаписываемые методы - массив триггеров, у которых в качестве условия записано тело метода.
Вызов такого метода - call TriggerEvaluate(массив_триггеров[массив_куда_записывается_тип[объект_структуры]]).
В нашем случае это будет выглядеть call TriggerEvaluate(массив_триггеров_OnTrack[массив_куда_записывается_тип[getTrack(h)]]).
StartThread создает новый поток для текущего ИИ, прерывая текущий поток. Есть лимит в 6 потоков на 1 ИИ. Нет лимита на количество операций в потоке.
Sleep - безглючная пауза потока.(TriggerSleepAction в ИИ не работает)
DisplayTextII - ничего не делает. Предназначена для форматированного вывода. Работает только с отладочной версией game.dll, которая не распространяется. Переход в отладочный режим не требуется.
Непосредственно в war3map.j не работают. Но можно вынести в .ai безглючный бесконечный цикл без доступа к триггерам, предметам и декорациям. Пока еще никому это не понадобилось.
Есть несколько нативок из common.ai, которые работают в war3map.j, но только со стандартными юнитами. Возможно .slk тут поможет. Если вы не собираетесь делать ИИ или ставить рекорды по оптимизации кода, то ничего из common.ai вам не пригодится.
Ну это погрешность в градусах, ( в JASS в радианах) между углом поворота Юнита и его целью, т.е чтобы кинуть молот бурь горному королю не обязательно смотреть прямо на цель, достаточно попасть в "это окно" у большинства юнитов 60 градусов, у мясников 120 и они могут стукнуть Юнита который стоит сбоку, даже не глядя на него...
Увы, нет - стройка абилками не полноценна, так что берем работника со способностью построить (её можно редактировать в константах)
В теории можно слепить абилку с помощью мемхака но, лич так и ненашел тот участок кода где создаются всякие прицелы, аое наведения, прилипшие к курсору полупрозрачные модели зданий...
да, верно. ID-приказ ничего не делает у spellbook-а. Никак триггерно не вызвается, не отслеживается. Но зато одинаковые книжки с ID-приказом склеиваются, точнее склеивается их содержимое. Это не значит, что иконка 2-го спелбука пропадет с панели команд. При открытий 1-ой книжки или 2-ой книжки у вас будет отображаться 10 скилов (там и там). Даже, триггерно не заставить юнитов юзать лежащие скилы в spellbook-е (у меня орк не хочет юзать скилы в спелбуке)
неизвестно. обычно открывается у игрока. А вот открыть и заюзать через триггеры не удается.
Работает) Adantarn, для тебя найден отличный и очень муторный способ наполнять спелбук, только мне пока не до того, чтобы его расписать. Может быть кто-то ещё решится это сделать.
» WarCraft 3 / Про JNGP
» WarCraft 3 / Поглощение урона
» WarCraft 3 / Способность передачи юнита игроку
» WarCraft 3 / Отличия
» WarCraft 3 / Ландшафт и склон
» WarCraft 3 / Проблемы с триггерными способностями
» WarCraft 3 / Выбор рас
» WarCraft 3 / Что я сделал не так?
» WarCraft 3 / Юниты убегают обратно
» WarCraft 3 / Атакуемый юнит
» WarCraft 3 / Способность на продажу юнита
» WarCraft 3 / Курьер в карту
» WarCraft 3 / Порча
» WarCraft 3 / Краши (Баг?)
» WarCraft 3 / Цвет декорации
» WarCraft 3 / как это сделать ?
» WarCraft 3 / Как правильно реализовать?
» WarCraft 3 / Как правильно импортировать
» WarCraft 3 / Триггерные способности
» WarCraft 3 / Триггер
» WarCraft 3 / Плавающий текст
» WarCraft 3 / вопрос по структурам(vJass)
» WarCraft 3 / Нативка в карте
» WarCraft 3 / Спеллбук